<template>
  <div class="transfer">
    <!-- 左侧列表 -->
    <div class="transfer__list left" :style="listStyle">
      <div class="list__header">
        <div class="check_box" v-if="isShowCheckAll" style="margin-left: -10px">
          <q-checkbox class="left-check-all" v-model="leftCheckAll" label="全选" color="primary" @input="getLeftChecked"/>
        </div>
        <div class="title">{{ leftTitle }}</div>
        <div class="count">{{ leftSelection.length }}/{{ leftData.length }}</div>
      </div>
      <div class="btn-box scroll-box">
        <select-input ref="selectInputIn"
                      :list="searchCondition"
                      @search="inputSearchOut"
                      :isLongth="false"
                      v-if="isShowSelectInput"
                      @clearSearchVal="clearSearchValOut" />
        <q-checkbox v-for="item in leftData"
                    :key="item[valueKey]"
                    v-model="leftSelection"
                    :val="item[valueKey]"
                    v-show="!item.checked"
                    :label="item[labelKey]" color="primary" />
      </div>
    </div>
    <div class="transfer__btn">
      <div>
        <q-btn
          color="primary"
          icon="iconfont icontubiao-44"
          class="margin-r-10 btn"
          @click="_moveToLeft"
          :disable="disabled || rightSelection.length === 0"
        />
        <q-btn
          color="primary"
          class="btn"
          icon="iconfont icontubiao-43"
          :disable="disabled || leftSelection.length === 0"
          @click="_moveToRight"
        />
      </div>
    </div>
    <!-- 右侧列表 -->
    <div class="transfer__list right" :style="listStyle">
      <div class="list__header">
        <div class="check_box" v-if="isShowCheckAll" style="margin-left: -10px">
          <q-checkbox  class="left-check-all" v-model="rightCheckAll" label="全选" color="primary" @input="getRightChecked"/>
        </div>
        <div class="title">{{ rightTitle }}</div>
        <div class="count">{{ rightSelection.length }}/{{ rightData.length }}</div>
      </div>
      <div class="btn-box scroll-box">
        <select-input ref="selectInputOut"
                      :list="searchCondition"
                      :isLongth="false"
                      v-if="isShowSelectInput"
                      @search="inputSearchIn"
                      @clearSearchVal="clearSearchValIn" />
        <q-checkbox v-for="item in rightData" :key="item[valueKey]" v-model="rightSelection" :val="item[valueKey]" :label="item[labelKey]" color="primary"  v-show="!item.checked"/>
      </div>
    </div>
  </div>
</template>

<script>
import _ from 'lodash'
import SelectInput from 'src/components/select-input'

export default {
  name: 'transfer-common',
  components: { SelectInput },
  props: {
    /**
     * 每个穿梭框的样式（Object 的形式表示）
     * @default { height: '480px', width: '200px' }
     */
    styles: {
      type: Object,
      default: () => {
        return {
          height: '480px',
          width: '200px'
        }
      }
    },

    /**
     * 穿梭框源数据，初始显示在左栏中
     * 默认情况下，源数据中 value 字段为数据的值，label 字段为显示的标签
     * 若要修改值或标签的键名，请指定 {@link #valueKey} 或 {@link #labelKey}
     * @default []
     */
    sourceData: {
      type: Array,
      default: () => []
    },

    /**
     * 被选择到右栏的数据的值
     * 值根据 {@link #valueKey} 从 {@link #data} 中取得
     * required
     */
    value: {
      type: Array,
      required: true
    },
    rightList: Array,
    /**
     * 在源数据中，表示数据值的键名
     * @see #data
     * @default 'value'
     */
    valueKey: {
      type: String,
      default: 'value'
    },

    /**
     * 在源数据中，表示标签的键名
     * @see #data
     * @default 'label
     */
    labelKey: {
      type: String,
      default: 'label'
    },

    /**
     * 左侧列表的标题
     * @default 'Left'
     */
    leftTitle: {
      type: String,
      default: ''
    },

    /**
     * 右侧列表的标题
     * @default 'Right'
     */
    rightTitle: {
      type: String,
      default: ''
    },

    disabled: {
      type: Boolean,
      default: false
    },
    isShowSelectInput: {
      type: Boolean,
      default: false
    },
    // 是否显示全选
    isShowCheckAll: {
      type: Boolean,
      default: false
    }
  },
  data () {
    return {
      // 左栏数据
      leftData: [],

      // 右栏数据
      rightData: [],

      // 选中的值
      selectedValues: [],

      //
      leftSelection: [],

      rightSelection: [],
      // 型号搜索条件
      searchCondition: [
        { id: 'model', name: '型号' },
        { id: 'spec', name: '规格' }
      ]
    }
  },
  methods: {
    init () {
      this.$refs.selectInputIn.clearSearchVal()
      this.$refs.selectInputOut.clearSearchVal()
    },
    // 搜索
    inputSearchOut (item, searchVal) {
      this.leftData = this.leftData.map(v => {
        const y = v
        y.checked = v[item.id] === searchVal ? 0 : 1
        return y
      })
      console.log(this.leftData)
    },
    clearSearchValOut () {
      this.leftData = this.leftData.map(v => {
        const item = v
        item.checked = false
        return item
      })
    },
    // 搜索
    inputSearchIn (item, searchVal) {
      this.rightData = this.rightData.map(v => {
        const y = v
        y.checked = v[item.id] === searchVal ? 0 : 1
        return y
      })
    },
    clearSearchValIn () {
      this.rightData = this.rightData.map(v => {
        const item = v
        item.checked = false
        return item
      })
    },
    getLeftChecked (val) {
      console.log(val)
      this.leftSelection = val ? this.leftData.filter(v => !v.checked).map(v => v[this.valueKey]) : []
    },
    getRightChecked (val) {
      this.rightSelection = val ? this.rightData.filter(v => !v.checked).map(v => v[this.valueKey]) : []
    },
    /**
     * 移动到右栏
     * @param value 欲移动的数据的 value
     */
    _moveToRight: function () {
      this.leftSelection.forEach(value => {
        this._moveToAnother(this.leftData, this.rightData, value)
        // 若已选择的 value 数组中无，则插入该数组
        !this.selectedValues.includes(value) && this.selectedValues.push(value)
      })
      this.leftSelection = []
      this.$emit('move', this.selectedValues)
    },

    /**
     * 移动到左栏
     * @param value 欲移动的数据的 value
     */
    _moveToLeft: function () {
      this.rightSelection.forEach(value => {
        this._moveToAnother(this.rightData, this.leftData, value)
        // 从已选择的 value 数组中移除
        this.selectedValues = this.selectedValues.filter(val => val !== value)
      })
      this.rightSelection = []
      this.$emit('move', this.selectedValues)
    },

    /**
     * 移动到另一栏
     * @param from {Array} 源栏
     * @param to {Array} 目标栏
     * @param value 欲移动的数据的 value
     */
    _moveToAnother: function (from, to, value) {
      // 筛选出 value 所属数据的数组下标
      let indices = from.reduce((acc, datum, index) => {
        if (datum[this.valueKey] === value) {
          acc.push(index)
        }
        return acc
      }, [])

      // 从 from 中删除，push 到 to
      indices.forEach(index => {
        to.push(...from.splice(index, 1))
      })
    }
  },
  computed: {
    // 每个穿梭框的样式
    listStyle: function () {
      return Object.assign({}, this.styles)
    },
    leftCheckAll: {
      get () {
        let member = this.leftData.map(v => v[this.valueKey]).length === this.leftSelection.length && this.leftSelection.length > 0
        if (this.leftSelection.length && !member) {
          member = null
        }
        return member
      },
      set (val) {
      }
    },
    rightCheckAll: {
      get () {
        let member = this.rightData.map(v => v[this.valueKey]).length === this.rightSelection.length && this.rightSelection.length > 0
        if (this.rightSelection.length && !member) {
          member = null
        }
        return member
      },
      set (val) {
      }
    }
  },
  watch: {
    // 源数据
    sourceData: {
      deep: true,
      immediate: true,
      handler: function (newVal) {
        // 如果数据为空。
        if (_.isEmpty(newVal)) {
          this.leftData = []
          return
        }
        // 追加新数据到左栏
        this.leftSelection = []
        this.leftData = newVal
      }
    },
    rightList: {
      handler (newValue) {
        this.rightSelection = []
        if (!_.isEmpty(newValue)) {
          this.rightData = newValue
          this.selectedValues = newValue.map(v => v.id)
        } else {
          this.rightData = []
          this.selectedValues = []
        }
      },
      deep: true,
      immediate: true
    },
    // 选中的值
    selectedValues: {
      deep: true,
      immediate: true,
      handler () {
        this.$emit('sourceChange', this.leftData)
        this.$emit('changeData', this.rightData)
        this.$emit('input', this.selectedValues)
      }
    }
  }
}
</script>

<style scoped lang="stylus">
.transfer {
  display flex

  &__btn{
    display flex
    align-items center
    margin 0 10px

    .btn{
      width 48px
      height 48px
    }
  }

  &__list {
    display flex
    flex-direction column
    position relative
    background white
    border 1px solid #D3D3D3
    border-radius 6px
    overflow-x hidden
    overflow-y: auto;

    .list__header {
      background #5F77FD
      color white
      height 40px!important
      width calc(100% + 2px)
      margin-left -1px
      line-height 40px
      padding 0 20px
      font-size 16px
      border-radius 6px 6px 0 0
      display: flex;
      justify-content space-between
      .left-check-all {
        /deep/ .q-checkbox__bg{
          border 1px solid white
        }
      }
      .count{
        font-size 12px
      }
    }
    >>>.q-checkbox__label{
      word-break break-all
    }
    .btn-box {
      display flex
      flex-direction column
      padding 10px
      overflow auto
      min-height calc(100% - 40px)

      .btn {
        box-shadow 0 0 3px 1px #D3D3D3
        color #333
        padding 0
        height 32px
        width 100%

        &:not(:last-child) {
          margin-bottom 11px
        }

        .btn-wrapper {
          width 100%
          display flex
          justify-content space-between
          align-items center
          padding 0 10px

          .label {
            font-size 14px
          }

          .arrow-icon {
            font-size 18px
          }
        }
      }
    }

    &.right .btn-box .btn {
      background #CFD6FE
    }
  }
}
</style>
